package ninja.awesome.game.gameobject;

import java.util.LinkedList;

import ninja.awesome.framework.Graphics;
import ninja.awesome.framework.Image;
import ninja.awesome.framework.Sound;
import ninja.awesome.game.Assets;
import ninja.awesome.game.MainGameScreen;
import ninja.awesome.game.NinjaGame;
import ninja.awesome.game.classes.Friendly;
import ninja.awesome.game.classes.Hostile;
import ninja.awesome.game.classes.Neutral;
import ninja.awesome.game.compat.Rectangle;
import ninja.awesome.game.main.Animation;
import ninja.awesome.game.main.Controller;
import ninja.awesome.game.main.Physics;
import ninja.awesome.game.main.Sprites;
import android.util.Log;

public class MyNinja extends GameObj implements Friendly {

	private static final int MAX_HEALTH = 450;
	private static final String TAG = MyNinja.class.getSimpleName();
	private int speedX, speedY;
	private int lives = 0;
	private int level = 1; // for ninja level
	private int nextLevel = 2; // for next ninja level
	private double ExperiencePoint = 0;
	private Sprites s;
	private Image[] mp;
	private Image[] e;
	private Image[] attacks;
	private Image[] ninjaHealthIcon;

	private boolean powerup = false;
	private boolean isDead = false;
	private boolean start = false;
	private boolean levelUp = false;
	private boolean isOpening = false;
	private int score = 0;

	private int jumpDistance = 50;
	private int jumpSpeed = 0;
	private int jumpTime = 0;
	private int throwTime = 0;
	private int timer = 0;
	private int deathTimer = 0;
	private int HEALTH = 450;
	private int ninjaRecoverTimer = 0;
	public LinkedList<Life> ll;

	private int deadAnim = 5;
	private int standAnim = 4;
	private int walkAnim = 9; // actually running!
	private int attackAnim = 3;
	private int jumpAnim = 12;
	private int throwAnim = 3;
	private int takingDamageAnim = 2;
	private int numAnim;
	private int randNumber = 0;

	private int remainingLives = 3;

	int anim = 0;

	Controller c;
	MainGameScreen game;
	Sound boom, power;
	Life l1, l2, l3, l4;
	Animation explosion;
	Animation blinking;

	Animation currentMovement;
	Animation currentAttack;
	Animation currentNinjaThrow;
	Animation currentDamagetaken;
	Animation currentHealthBar;

	private String direction = "right"; // setting the direction: facing right
										// or facing left.
	private boolean isRunning = false;
	private boolean isAttacking = false; // if a ninja is attacking!
	private boolean isJumping = false; // when ninja is jumping
	private boolean isDoubleJumping = false; // when ninja is doubling jumping
	private boolean isThrowing = false;
	private int savedY;

	public MyNinja(int x, int y, MainGameScreen game, Controller c, Sprites s) {
		super(x, y);
		this.savedY = y;
		this.game = game;
		this.c = c;
		this.s = s;
		mp = this.s.getMP(); // got from Sprites.java
		ninjaHealthIcon = this.s.getninjaHealthIcon();
		e = this.s.getExplosion2();
		attacks = this.s.getAttack();

		explosion = new Animation(5, mp[0], 175, 154, 5);

		blinking = new Animation(10, mp[0], 32, 32, 3);

		boom = Assets.boom;
		power = Assets.power;

		currentMovement = new Animation(6, mp[0], 175, 154, 4);
		currentAttack = new Animation(4, mp[0], 175, 154, 3, game.getCombo());
		currentNinjaThrow = new Animation(3, mp[0], 175, 154, 3);
		currentDamagetaken = new Animation(2, mp[0], 175, 153, 2);

	}

	@Override
	public void update() {
		// currentHealthBar.runAnimation();

		// Dead explosion
		if (getHEALTH() <= 0) {
			if (!isDead) {
				Assets.die.play(1f);
				setIsDead(true);
				deathTimer = 0;
				if (this.getLives() == 0) {
					game.setGameOver(false);
				}
			}
			explosion.runtAnimationWithoutLoop();
			if (deathTimer == 40) {
				remainingLives --;
				this.SetX(xLoc);
				this.SetY(yLoc);
				setHEALTH(450);
				setIsDead(false);
				this.setPowerup(false);
				this.setStart(true);
				explosion.setTempNumber(0);
			}
			deathTimer++;
		}

		if (!isDead) {
			// xLoc += speedX;
			yLoc += speedY;
			xLoc += speedX;
			// SET BOUNDS
			if (xLoc <= 600) {
				xLoc = 600;
			}
			if (xLoc >= 600) {
				xLoc = 600;
			}

			if (isJumping == false) {
				updateYLoc();
			} else {
				if (jumpTime < 25) {
					jumpSpeed = 8;
					yLoc -= jumpSpeed;
				} else if (jumpTime >= 30 && jumpTime <= 47) {
					yLoc += jumpSpeed;
				} else if (jumpTime > 47) {
					game.setJumping(false);
					jumpTime = 0;
					jumpSpeed = 0;
					isJumping = false;
					yLoc = this.savedY;
				}
				jumpTime++;
				// System.out.println(jumpSpeed);
				// this is for the test!
			}

			if (throwTime > 10) {
				// game.setThrown(false);
				throwTime = 0;
				isThrowing = false;
			}
			throwTime++;
			// ENEMY COLLISIONS
			for (int i = 0; i < game.hl.size(); i++) {
				Hostile tempH = game.hl.get(i);

				/*
				 * if (Physics.collision(this, tempH)) { if (!tempH.getIsDead())
				 * { boom.play(false); setHEALTH(getHEALTH() - 25); }
				 * tempH.setIsDead(false); }
				 */

			}

			// POWER UPS
			for (int i = 0; i < c.getNeutral().size(); i++) {
				Neutral tempN = c.getNeutral().get(i);

				if (Physics.collision(tempN, this)) {
					c.removeNeutral(tempN);

					if (!powerup) {
						power.play(1f);
						setPowerup(true);
					}

				}
			}
			for (int i = 0; i < c.getBuilding().size(); i++) {
				Building tempBldg = c.getBuilding().get(i);
				if (Physics.collision(tempBldg, this) && this.isOpening)
					tempBldg.setIsUsed(true);
			}

			if (getHEALTH() <= 0) {
				setIsDead(true);
				boom.play(1f);
				// setLives(getLives() - 1);
				if (getLives() > 0) {

				}
			}
		}
		if (timer < 60) {
			blinking.runAnimation();
		}

		currentMovement.runAnimation();
	}

	private void updateYLoc() {
		if (yLoc <= NinjaGame.ROAD_Y - 154) {
			yLoc = NinjaGame.ROAD_Y - 154;
		}
		if (yLoc >= NinjaGame.ROAD_Y + NinjaGame.ROAD_HEIGHT - 170) {
			yLoc = NinjaGame.ROAD_Y + NinjaGame.ROAD_HEIGHT - 170;
		}
	}

	@Override
	public void draw(Graphics g) {
		if (!isDead) {
			if (start) {
				if (timer < 60) {
					blinking.drawAnimation(g, xLoc, yLoc);
					this.setStart(false);
					timer = 0;
				}
				timer++;
			}

			// currentHealthBar.setAction(0);
			// currentHealthBar.drawAnimation(g, 2, 2);

			if (isRunning == false && !isAttacking && !isThrowing && !isJumping) {
				if (direction.equals("left")) {
					currentMovement.setAction(1);
					currentMovement.setSpeed(6);// animation speed
					currentMovement.setImageNumber(this.standAnim);
					currentMovement.drawAnimation(g, xLoc, yLoc);
				} else {
					currentMovement.setAction(0);
					currentMovement.setSpeed(6);// animation speed
					currentMovement.setImageNumber(this.standAnim);
					currentMovement.drawAnimation(g, xLoc, yLoc);
				}

			} else if (isAttacking == true) {
				if (direction.equals("left")) {
					currentMovement.setAction(5);
					currentMovement.setSpeed(3);// animation speed
					currentMovement.setImageNumber(this.attackAnim);
					currentMovement.drawAnimation(g, xLoc, yLoc);
				} else {
					currentMovement.setAction(4);
					currentMovement.setSpeed(3);// animation speed
					currentMovement.setImageNumber(this.attackAnim);
					currentMovement.drawAnimation(g, xLoc, yLoc);
				}

			} else if (isJumping) {
				if (direction.equals(("left"))) {
					// System.out.println("Jumping!");
					currentMovement.setAction(7);
					currentMovement.setSpeed(6);// animation speed
					currentMovement.setImageNumber(this.jumpAnim);
					currentMovement.drawAnimation(g, xLoc, yLoc);
				} else {
					currentMovement.setAction(6);// changing animation
					currentMovement.setSpeed(6);// animation speed
					currentMovement.setImageNumber(this.jumpAnim);
					currentMovement.drawAnimation(g, xLoc, yLoc);
				}

			} else if (isThrowing == true) {
				if (direction.equals("left")) {
					currentMovement.setAction(9);
					currentMovement.setSpeed(2);// animation speed
					currentMovement.setImageNumber(this.throwAnim);
					currentMovement.drawAnimation(g, xLoc, yLoc);
				} else {
					currentMovement.setAction(8);
					currentMovement.setSpeed(2);// animation speed
					currentMovement.setImageNumber(this.throwAnim);
					currentMovement.drawAnimation(g, xLoc, yLoc);
				}

			} else if (isRunning) {
				if (direction.equals("left")) {
					currentMovement.setAction(3);
					currentMovement.setSpeed(3);// animation speed
					currentMovement.setImageNumber(this.walkAnim);
					currentMovement.drawAnimation(g, xLoc, yLoc);
				} else {
					currentMovement.setAction(2);
					currentMovement.setSpeed(3);// animation speed
					currentMovement.setImageNumber(this.walkAnim);
					currentMovement.drawAnimation(g, xLoc, yLoc);
				}

			} else {
				if (direction.equals("right"))
					explosion.setAction(12);
				else
					explosion.setAction(13);

				explosion.drawAnimation(g, xLoc, yLoc);

			}

			// System.out.println(yLoc);

			for (int i = 0; i < this.getLives(); i++) {
				// Life tempL = ll.get(i);
				// tempL.draw(g);
			}

		} else {
			if (direction.equals("left")) {
				explosion.setAction(13);
			} else {
				explosion.setAction(12);
			}
			explosion.drawAnimation(g, xLoc, yLoc);
		}
	}

	@Override
	public Rectangle getBounds() {
		return new Rectangle(xLoc, yLoc, 100, 100);
	}

	// GETTERS
	@Override
	public int getX() {
		return xLoc;
	}

	@Override
	public int getY() {
		return yLoc;
	}

	public int getSpeedX() {
		return speedX;
	}

	public int getSpeedY() {
		return speedY;
	}

	public int getjumpDistance() {
		return jumpDistance;
	}

	// Setters
	public void SetX(int x) {
		this.xLoc = x;
	}

	public void SetY(int y) {
		this.yLoc = y;
	}

	public void setjumpDistance(int jumpDistance) {
		this.jumpDistance = jumpDistance;

	}

	public void setSpeedX(int speed) {
		this.speedX = speed;
	}

	public void setSpeedY(int speed) {
		this.speedY = speed;
	}

	public void setIsDead(boolean b) {
		isDead = b;
	}

	public void setLives(int n) {
		this.lives = n;
	}

	public int getLives() {
		return this.lives;
	}

	public boolean isPowerup() {
		return powerup;
	}

	public boolean isAttacking() {
		return isAttacking;
	}

	public void setPowerup(boolean powerup) {
		this.powerup = powerup;
	}

	public int getHEALTH() {
		return HEALTH;
	}

	public void setHEALTH(int hEALTH) {
		HEALTH = hEALTH;
	}

	public int getScore() {
		return score;
	}

	public void setScore(int score) {
		this.score = score;
	}

	public int getTimer() {
		return timer;
	}

	public void setTimer(int timer) {
		this.timer = timer;
	}

	public boolean isStart() {
		return start;
	}

	public void setStart(boolean start) {
	}

	public void setDirection(String direction) {
		this.direction = direction;

	}

	public String getDirection() {
		return this.direction;
	}

	// add the setter running for running animation
	public void setIsRunning(boolean isRunning) {
		this.isRunning = isRunning;
	}

	public void setIsAttacking(boolean isAttacking) {
		this.isAttacking = isAttacking;
	}

	public void setIsJumping(boolean isJumping) {
		if (!this.isJumping && isJumping) {
			Log.w(TAG, "yLoc before jump: " + this.yLoc);
			savedY = this.yLoc;
		}
		this.isJumping = isJumping;
	}

	public void setIsDoubeJumping(boolean isDoubleJumping) {
		this.isDoubleJumping = isDoubleJumping;
	}

	public void setIsThrowing(boolean isThrowing) {
		this.isThrowing = isThrowing;
	}

	public void setIsOpening(boolean isOpening) {
		this.isOpening = isOpening;
	}

	public boolean getIsOpening() {
		return this.isOpening;
	}

	public void setExperiencePoint(double ExperiencePoint) {
		this.ExperiencePoint = ExperiencePoint;

	}

	public double getExperiencePoint() {
		return this.ExperiencePoint;
	}

	public void setLevel(int level) {
		this.level = level;
	}

	public int getLevel() {
		return this.level;
	}

	public void setNextLevel(int nextLevel) {
		this.nextLevel = nextLevel;
	}

	public int getNextLevel() {
		return this.nextLevel;
	}

	public int getHealthPercent() {
		return Math.round(this.HEALTH * 100f / MAX_HEALTH);
	}

	public int getRemainingLives() {
		return remainingLives;
	}

	public void setRemainingLives(int remainingLives) {
		this.remainingLives = remainingLives;
	}

}
